/*
 * Copyright (C) 2018-2025 Toshiaki Maki <makingx@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package am.ik.yavi.arguments;

import java.util.Objects;

import am.ik.yavi.fn.Function1;
import am.ik.yavi.jsr305.Nullable;

/**
 * A container class that holds 1 arguments, providing type-safe access to each argument
 * and mapping functionality to transform these arguments.
 *
 * Generated by https://github.com/making/yavi/blob/develop/scripts/generate-args.sh
 *
 * @param <A1> the type of argument at position 1
 * @since 0.3.0
 */
public final class Arguments1<A1> {

	private final A1 arg1;

	/**
	 * Creates a new Arguments1 instance with the provided arguments.
	 * @param arg1 the argument at position 1
	 */
	Arguments1(@Nullable A1 arg1) {
		this.arg1 = arg1;
	}

	/**
	 * Returns the argument at position 1.
	 * @return the argument at position 1
	 */
	@Nullable
	public A1 arg1() {
		return this.arg1;
	}

	/**
	 * Applies the provided mapping function to all arguments contained in this instance.
	 * @param <X> the type of the result
	 * @param mapper the function to apply to the arguments
	 * @return the result of applying the mapper function to the arguments
	 */
	public <X> X map(Function1<? super A1, ? extends X> mapper) {
		return mapper.apply(arg1);
	}

	/**
	 * Appends an additional argument to create a new, larger Arguments instance.
	 * @param <B> the type of the argument to append
	 * @param arg the argument to append
	 * @return a new Arguments2 instance with the additional argument
	 * @since 0.16.0
	 */
	public <B> Arguments2<A1, B> append(@Nullable B arg) {
		return new Arguments2<>(this.arg1, arg);
	}

	/**
	 * Prepends an additional argument to create a new, larger Arguments instance.
	 * @param <B> the type of the argument to prepend
	 * @param arg the argument to prepend
	 * @return a new Arguments2 instance with the additional argument
	 * @since 0.16.0
	 */
	public <B> Arguments2<B, A1> prepend(@Nullable B arg) {
		return new Arguments2<>(arg, this.arg1);
	}

	/**
	 * Indicates whether some other object is "equal to" this one.
	 * @param obj the reference object with which to compare
	 * @return true if this object is the same as the obj argument; false otherwise
	 */
	@Override
	@SuppressWarnings("unchecked")
	public boolean equals(@Nullable Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || getClass() != obj.getClass()) {
			return false;
		}
		Arguments1<A1> that = (Arguments1<A1>) obj;
		return Objects.equals(this.arg1, that.arg1);
	}

	/**
	 * Returns a hash code value for the object.
	 * @return a hash code value for this object
	 */
	@Override
	public int hashCode() {
		return Objects.hash(this.arg1);
	}

	/**
	 * Returns a string representation of the object.
	 * @return a string representation of the object
	 */
	@Override
	public String toString() {
		return "Arguments1{" + "arg1=" + this.arg1 + "}";
	}

}
